
#include <QVector4D>

#include "entity/cow.h"
#include "entity/ufo.h"
#include "object/object.h"

Object* UFO::s_pkUFOObject = new Object();

UFO::UFO(QObject* pkParent)
    : QObject(pkParent),
      m_velocity(5.0),
      m_eState(Loading),
      m_teleportRadius(2),
      m_teleportVelocity(0.5),
      m_bIsTeleportReady(true),
      m_uiTeleportReloadDelay(2000)
{
    // Set reload timer.
    m_kReloadTimer.setSingleShot(true);
    m_kReloadTimer.setInterval(m_uiTeleportReloadDelay);
    QObject::connect(&m_kReloadTimer, SIGNAL(timeout()), this, SLOT(reload()));

    // Set entity object.
    Q_ASSERT(s_pkUFOObject->isValid());
    setObject(*s_pkUFOObject);
}

UFO::~UFO()
{
}

Object& UFO::object()
{
    return *s_pkUFOObject;
}

qreal UFO::velocity() const
{
    return m_velocity;
}

Path& UFO::path()
{
    return m_kPath;
}

QVector3D UFO::position() const
{
    return QVector3D(matrix().column(3));
}

qreal UFO::teleportRadius() const
{
    return m_teleportRadius;
}

qreal UFO::teleportVelocity() const
{
    return m_teleportVelocity;
}

Cow& UFO::loadedCow(quint8 uiIndex) const
{
    Q_ASSERT(uiIndex < 2);
    return *m_kLoadedCows.at(uiIndex);
}

bool UFO::isTeleportReady() const
{
    return m_bIsTeleportReady;
}

Sphere UFO::body() const
{
    Q_ASSERT(s_pkUFOObject->isValid());
    return Sphere(position(), (s_pkUFOObject->width() + s_pkUFOObject->depth()) / 2 / 2);
}

void UFO::setPosition(const QVector3D& rkPosition)
{
    QMatrix4x4 kResult = matrix();
    kResult.setColumn(3, QVector4D(rkPosition, 1));
    setMatrix(kResult);
}

void UFO::setPosition(qreal x, qreal y, qreal z)
{
    QMatrix4x4 kResult = matrix();
    kResult.setColumn(3, QVector4D(x, y, z, 1));
    setMatrix(kResult);
}

UFO::State UFO::state() const
{
    return m_eState;
}

void UFO::setState(State eState)
{
    m_eState = eState;
}

bool UFO::isEmpty() const
{
    return !m_kLoadedCows.count();
}

bool UFO::isFull() const
{
    return m_kLoadedCows.count() == 2;
}

void UFO::load(Cow& rkCow)
{
    m_kLoadedCows.enqueue(&rkCow);
}

Cow& UFO::unload()
{
    Q_ASSERT(!m_kLoadedCows.isEmpty());

    return *m_kLoadedCows.dequeue();
}

void UFO::clear()
{
    m_kLoadedCows.clear();
}

void UFO::fire()
{
    // Start the reloading timer.
    m_bIsTeleportReady = false;
    m_kReloadTimer.start();
}

void UFO::reload()
{
    m_bIsTeleportReady = true;
}
